package com.sens.alipay;

import com.sens.common.Log;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.util.EntityUtils;

import java.lang.reflect.Method;
import java.net.URLDecoder;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

public class TestHooker {
    public TestHooker(final ClassLoader classLoader) throws Throwable {
        Class HttpHost = classLoader.loadClass("org.apache.http.HttpHost");
        Class HttpRequest = classLoader.loadClass("org.apache.http.HttpRequest");
        Class HttpContext = classLoader.loadClass("org.apache.http.protocol.HttpContext");
        XposedHelpers.findAndHookMethod("com.alipay.mobile.common.transportext.biz.spdy.http.AndroidSpdyHttpClient", classLoader, "execute", HttpHost, HttpRequest, HttpContext, executeHooker);

//        XposedHelpers.findAndHookConstructor("org.apache.http.message.BasicNameValuePair", classLoader, String.class, String.class, BasicNameValuePairHooker);

//        XposedHelpers.findAndHookMethod("com.alipay.mobile.common.transport.http.HttpUrlRequest",classLoader,"setReqData",byte[].class,setReqDataHooker);

//        XposedHelpers.findAndHookConstructor("com.alipay.mobile.common.rpc.transport.AbstractRpcCaller", classLoader, Method.class, int.class, String.class, byte[].class, String.class, boolean.class, AbstractRpcCallerHooker);
        new Thread(new Runnable() {
            @Override
            public void run() {
                Class HttpUrlRequestClass = null;
                try {
                    HttpUrlRequestClass = classLoader.loadClass("com.alipay.mobile.common.transport.http.HttpUrlRequest");
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
                for (Method method : HttpUrlRequestClass.getDeclaredMethods()) {
                    if(method.getName().startsWith("set")
                            ||method.getName().startsWith("add"))
                    XposedBridge.hookMethod(method, allHooker);
                }
            }
        }).start();
    }

    private XC_MethodHook allHooker = new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(final MethodHookParam param) throws Throwable {
            super.afterHookedMethod(param);
            StringBuilder sb = new StringBuilder("HttpUrlRequest's Method::" + param.method.getName());
            for (int i = 0; i < param.args.length; i++) {
                if(param.args[i] instanceof byte[]){
                    Log.printFunction();
                    sb.append(" arg" + i + ":" + new String((byte[])param.args[i]));
                }else
                    sb.append(" arg" + i + ":" + param.args[i]);
            }
            Log.i(sb.toString());
        }
    };

    private XC_MethodHook AbstractRpcCallerHooker = new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
            super.beforeHookedMethod(param);
            for (int i = 0; i < param.args.length; i++) {
                Log.i("AbstractRpcCaller:arg" + i + ":" + param.args[i]);
            }
        }
    };
//    private XC_MethodHook setReqDataHooker = new XC_MethodHook() {
//        @Override
//        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//            super.afterHookedMethod(param);
//            Log.printFunction();
//            Log.i("setReqData:"+new String((byte[])param.args[0]));
//        }
//    };

//    private XC_MethodHook BasicNameValuePairHooker = new XC_MethodHook() {
//        @Override
//        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
//            super.beforeHookedMethod(param);
//            Log.i("BasicNameValuePair:" + param.args[0] + "=" + param.args[1]);
////            Log.printFunction();
//        }
//    };


    private XC_MethodHook executeHooker = new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            super.afterHookedMethod(param);
//            Log.printFunction();
            for (int i = 0; i < param.args.length; i++) {
                Log.i("execute arg" + i + ":" + param.args[i]);
            }
            StringBuilder sb = new StringBuilder("execute--->");
            String postParam = null;
            if (param.args[1] instanceof HttpGet) {
                HttpGet get = (HttpGet) param.args[1];
                Header headers[] = get.getAllHeaders();
                sb.append(" get:");
                sb.append(URLDecoder.decode(get.getURI().toString(), "utf-8"));
                sb.append("\nheaders:");
                for (Header header : headers) {
                    sb.append(header.getName());
                    sb.append("=");
                    sb.append(header.getValue());
                    sb.append("&");
                }
            } else if (param.args[1] instanceof HttpPost) {
                HttpPost post = (HttpPost) param.args[1];
                Header headers[] = post.getAllHeaders();
                sb.append(" post:");
                sb.append(URLDecoder.decode(post.getURI().toString(), "utf-8"));
                sb.append("?");
                postParam = EntityUtils.toString(post.getEntity());
//                try {
//                    Log.i("getEntity---" );
//                            Log.i("getEntity:" + new String(EntityUtils.toByteArray(post.getEntity())));
//                }catch (Exception e){e.printStackTrace();}

                sb.append("postParam<" + postParam + ">");
                sb.append(URLDecoder.decode(postParam, "utf-8"));
                sb.append("\nheaders:");
                for (Header header : headers) {
                    sb.append(header.getName());
                    sb.append("=");
                    sb.append(header.getValue());
                    sb.append("&\n");
                }
            }
            Log.i(sb.toString());
            HttpResponse response = (HttpResponse) param.getResult();
            String responseString = EntityUtils.toString(response.getEntity());
            ByteArrayEntity byteArrayEntity = new ByteArrayEntity(responseString.getBytes("utf-8"));
            response.setEntity(byteArrayEntity);
            for (int i = 0; i < responseString.length(); i += 3000) {
                Log.i(responseString.substring(i, responseString.length() < i + 3000 ? responseString.length() : i + 3000));
            }
        }
    };

}
